Modify the hardware based on the previous HDMI project:
Since the default output of ZYNQ's PS using the EMIO method is GMII, and our network part (adapter card) chip RTL8211 outputs RGMII, we need to add a GMII to RGMII conversion IP module (Gmii to Rgmii).
Open the GMII TO RGMII module and change the settings as shown below.
Also, because GMII TO RGMII is active-high reset, but ZYNQ outputs an active-low reset, we need to add an inverter (search for utility, and in the retrieved options, select utility vector logic).
In the settings page, change it to not (inverter) and set the bit width to 1.
Since the configuration requirements for the network port conflict with the HDMI configuration requirements, we need to modify the ZYNQ settings:
Connect according to the diagram below:
After modifying the block design, save it, then regenerate "Generate Output Products" and "Create HDL Wrapper". Next, we need to modify the constraints file to assign pins for the Ethernet1 interface according to the schematic.
Save the constraints file, then proceed with the subsequent operations to regenerate the BIT file.
Since it can share the same project with Ethernet0, there is no need to create a new project. However, some modifications are still needed:
In the project's code files, change the network port to Ethernet1:
Modify the lwip library files:
Modify the lwip211.mld file:
According to the software installation path, mine is at C:\Xilinx\Vitis\2021.1\data\embeddedsw\ThirdParty\sw_services\lwip211_v1_5\data. Add the following content:
BEGIN CATEGORY emio_options PARAM name = emio_options, desc = "Settings for ETH using EMIO in PL"; PARAM name = use_gmii2rgmii_core_on_eth0, desc = "Settings for ETH0 using GMII to RGMII ip core in PL", type = bool, default = false; PARAM name = use_gmii2rgmii_core_on_eth1, desc = "Settings for ETH1 using GMII to RGMII ip core in PL", type = bool, default = false; PARAM name = gmii2rgmii_core_address_on_eth0, desc = "Settings for ETH0's PHY address of GMII to RGMII ip core in PL", type = int, default = 0; PARAM name = gmii2rgmii_core_address_on_eth1, desc = "Settings for ETH1's PHY address of GMII to RGMII ip core in PL", type = int, default = 0; END CATEGORYAfter that, open the BSP and modify the settings as shown in the figure below:
Modify the lwip211.tcl file (file path: C:\Xilinx\Vitis\2021.1\data\embeddedsw\ThirdParty\sw_services\lwip211_v1_5\data), and add the following content:
xproc generate_lwip_opts {libhandle} { .... # Content added begins # EMIO options set use_gmii2rgmii_core_on_eth0 [common::get_property CONFIG.use_gmii2rgmii_core_on_eth0 $libhandle] set use_gmii2rgmii_core_on_eth1 [common::get_property CONFIG.use_gmii2rgmii_core_on_eth1 $libhandle] set gmii2rgmii_core_address_on_eth0 [common::get_property CONFIG.gmii2rgmii_core_address_on_eth0 $libhandle] set gmii2rgmii_core_address_on_eth1 [common::get_property CONFIG.gmii2rgmii_core_address_on_eth1 $libhandle]
if { $use_gmii2rgmii_core_on_eth0 == true } { puts $lwipopts_fd "\#define XPAR_GMII2RGMIICON_0N_ETH0_ADDR $gmii2rgmii_core_address_on_eth0" } if { $use_gmii2rgmii_core_on_eth1 == true } { puts $lwipopts_fd "\#define XPAR_GMII2RGMIICON_0N_ETH1_ADDR $gmii2rgmii_core_address_on_eth1" } # Content added ends
puts $lwipopts_fd "\#endif" close $lwipopts_fd}Similarly, after making the modifications, be sure to right-click the platform project and select Build Project:
In the hardware design of V1.1.0, the PHY chip for the Ethernet interface has been replaced from RTL8211E to RTL8211F. Currently, the LWIP driver provided in vitis does not support RTL8211F, so it is necessary to modify the source code of LWIP accordingly.
The file that needs to be modified is C:\Xilinx\Vitis\2021.1\data\embeddedsw\ThirdParty\sw_services\lwip211_v1_5\src\contrib\ports\xilinx\netif\xemacpsif_physpeed.c
xxxxxxxxxx// Add RTL8211F macro definition.
// Modified the get_Realtek_phy_speed function to support RTL8211F.static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr){ ... u16_t phy_identity2 = 0; ... xil_printf("autonegotiation complete \r\n");
//Identify PHY model XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG, &phy_identity2);
switch (phy_identity2) { case PHY_REALTEK_RTL8211F: { xil_printf("detected RTL8211F \r\n"); //Switch to page 0xd08 XEmacPs_PhyWrite(xemacpsp, phy_addr, RTL8211F_PAGSR, RTL8211F_MIICR_PAGE); // enable TXDLY XEmacPs_PhyRead(xemacpsp, phy_addr, RTL8211F_MIICR, &control); XEmacPs_PhyWrite(xemacpsp, phy_addr, RTL8211F_MIICR, control | RTL8211F_TXDLY_MASK);
//Switch to page 0xA43 XEmacPs_PhyWrite(xemacpsp, phy_addr, RTL8211F_PAGSR, RTL8211F_PHYSR_PAGE); XEmacPs_PhyRead(xemacpsp, phy_addr, RTL8211F_PHYSR, &status_speed); //Switch back to default page XEmacPs_PhyWrite(xemacpsp, phy_addr, RTL8211F_PAGSR, 0); //If there is link if (status_speed & RTL8211F_PHYSR_LINK_MASK) { temp_speed = status_speed & RTL8211F_PHYSR_SPEED_MASK;
if (temp_speed == RTL8211F_PHYSR_1000) return 1000; else if(temp_speed == RTL8211F_PHYSR_100) return 100; else return 10; } break; } case PHY_REALTEK_RTL8211E: xil_printf("detected RTL8211E \r\n"); //RTL8211E fall-back to default Realtek behaviour default: { XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG, &status_speed); if (status_speed & 0x400) { temp_speed = status_speed & IEEE_SPEED_MASK;
if (temp_speed == IEEE_SPEED_1000) return 1000; else if(temp_speed == IEEE_SPEED_100) return 100; else return 10; } break; } } return XST_FAILURE;}After making the changes, restart the Vitis process and recompile the platform project.
You can also download the modified lwip compressed package from GitHub.
After the project is compiled successfully, connect the development board's JTAG to the computer using a Type-C USB cable, and use another Type-C USB cable to connect the board's PS UART to the computer. Connect an Ethernet cable between the board and the computer. Open a serial debugging tool like MobaXterm on the computer and establish a connection with the development board's PS UART. Through the serial port, you can observe that the network has started, the IP address is 192.168.3.150, and the network port is port 7.
Using a Windows computer on the same router network segment (you can use the host's IP), ping this IP address. If the ping is successful, it means the network connection is established:
After connecting with a network debugging assistant, whatever data you send will be received back through the network (the port number is set to 7, and the IP address is set according to the board's IP address read from the serial port earlier). Run a TCP client on the computer: